home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Linux / SLAX 6.0.8 / slax-6.0.8.iso / slax / base / 006-devel.lzm / usr / include / kparts / part.h < prev    next >
Encoding:
C/C++ Source or Header  |  2006-07-22  |  20.6 KB  |  703 lines

  1. /* This file is part of the KDE project
  2.    Copyright (C) 1999 Simon Hausmann <hausmann@kde.org>
  3.              (C) 1999 David Faure <faure@kde.org>
  4.  
  5.    This library is free software; you can redistribute it and/or
  6.    modify it under the terms of the GNU Library General Public
  7.    License as published by the Free Software Foundation; either
  8.    version 2 of the License, or (at your option) any later version.
  9.  
  10.    This library is distributed in the hope that it will be useful,
  11.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.    Library General Public License for more details.
  14.  
  15.    You should have received a copy of the GNU Library General Public License
  16.    along with this library; see the file COPYING.LIB.  If not, write to
  17.    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  18.    Boston, MA 02110-1301, USA.
  19. */
  20. #ifndef _KPART_H
  21. #define _KPART_H
  22.  
  23. #include <qstring.h>
  24. #include <qdom.h>
  25. #include <qguardedptr.h>
  26. #include <kurl.h>
  27.  
  28. #include <kxmlguiclient.h>
  29.  
  30. class KInstance;
  31. class QWidget;
  32. class KAction;
  33. class KActionCollection;
  34. class QEvent;
  35. struct QUnknownInterface;
  36.  
  37. namespace KIO {
  38.   class Job;
  39. }
  40.  
  41. namespace KParts
  42. {
  43.  
  44. class PartManager;
  45. class Plugin;
  46. class PartPrivate;
  47. class PartActivateEvent;
  48. class PartSelectEvent;
  49. class GUIActivateEvent;
  50. class PartBasePrivate;
  51.  
  52. /**
  53.  *  Base class for all parts.
  54.  *
  55.  *  @short Base class for all parts.
  56.  */
  57. class KPARTS_EXPORT PartBase : virtual public KXMLGUIClient
  58. {
  59.     friend class PartBasePrivate;
  60. public:
  61.  
  62.   /**
  63.    *  Constructor.
  64.    */
  65.   PartBase();
  66.  
  67.   /**
  68.    *  Destructor.
  69.    */
  70.   virtual ~PartBase();
  71.  
  72.   /**
  73.    *  Internal method. Called by KParts::Part to specify the parent object for plugin objects.
  74.    *
  75.    * @internal
  76.    */
  77.   void setPartObject( QObject *object );
  78.   QObject *partObject() const;
  79.  
  80. protected:
  81.   /**
  82.    * Set the instance ( KInstance) for this part.
  83.    *
  84.    * Call this *first* in the inherited class constructor,
  85.    * because it loads the i18n catalogues.
  86.    */
  87.   virtual void setInstance( KInstance *instance );
  88.  
  89.   /**
  90.    * Set the instance ( KInstance) for this part.
  91.    *
  92.    * Call this *first* in the inherited class constructor,
  93.    * because it loads the i18n catalogues.
  94.    */
  95.   virtual void setInstance( KInstance *instance, bool loadPlugins );
  96.  
  97.   /**
  98.    * We have three different policies, whether to load new plugins or not. The
  99.    * value in the KConfig object of the KInstance object always overrides
  100.    * LoadPlugins and LoadPluginsIfEnabled.
  101.    */
  102.   enum PluginLoadingMode {
  103.     /**
  104.      * Don't load any plugins at all.
  105.      */
  106.     DoNotLoadPlugins = 0,
  107.     /**
  108.      * Load new plugins automatically. Can be
  109.      * overridden by the plugin if it sets
  110.      * EnabledByDefault=false in the corresponding
  111.      * .desktop file.
  112.      */
  113.     LoadPlugins = 1,
  114.     /**
  115.      * New plugins are disabled by default. Can be
  116.      * overridden by the plugin if it sets
  117.      * EnabledByDefault=true in the corresponding
  118.      * .desktop file.
  119.      */
  120.     LoadPluginsIfEnabled = 2
  121.   };
  122.  
  123.   /**
  124.    * Load the Plugins honoring the PluginLoadingMode.
  125.    *
  126.    * If you call this method in an already constructed GUI (like when the user
  127.    * has changed which plugins are enabled) you need to add the new plugins to
  128.    * the KXMLGUIFactory:
  129.    * \code
  130.    * if( factory() )
  131.    * {
  132.    *   QPtrList<KParts::Plugin> plugins = KParts::Plugin::pluginObjects( this );
  133.    *   QPtrListIterator<KParts::Plugin> it( plugins );
  134.    *   KParts::Plugin * plugin;
  135.    *   while( ( plugin = it.current() ) != 0 )
  136.    *   {
  137.    *     ++it;
  138.    *     factory()->addClient(  plugin );
  139.    *   }
  140.    * }
  141.    * \endcode
  142.    */
  143.   void loadPlugins( QObject *parent, KXMLGUIClient *parentGUIClient, KInstance *instance );
  144.  
  145.   /**
  146.    * For a KParts::Part: call this before setInstance().
  147.    * For a KParts::MainWindow: call this before createGUI().
  148.    */
  149.   void setPluginLoadingMode( PluginLoadingMode loadingMode );
  150.  
  151. private:
  152.     PartBasePrivate *d;
  153.     QObject *m_obj;
  154. };
  155.  
  156. /**
  157.  * Base class for parts.
  158.  *
  159.  * A "part" is a GUI component, featuring:
  160.  * @li A widget embeddedable in any application.
  161.  * @li GUI elements that will be merged in the "host" user interface
  162.  * (menubars, toolbars... ).
  163.  *
  164.  * <b>About the widget:</b>\n
  165.  *
  166.  * Note that KParts::Part does not inherit QWidget.
  167.  * This is due to the fact that the "visual representation"
  168.  * will probably not be a mere QWidget, but an elaborate one.
  169.  * That's why when implementing your KParts::Part (or derived)
  170.  * you should call KParts::Part::setWidget() in your constructor.
  171.  *
  172.  * <b>About the GUI elements:</b>\n
  173.  *
  174.  * Those elements trigger actions, defined by the part (action()).
  175.  * The layout of the actions in the GUI is defined by an XML file (setXMLFile()).
  176.  *
  177.  * See also ReadOnlyPart and ReadWritePart, which define the
  178.  * framework for a "viewer" part and for an "editor"-like part.
  179.  * Use Part directly only if your part doesn't fit into those.
  180.  */
  181. class KPARTS_EXPORT Part : public QObject, public PartBase
  182. {
  183.     Q_OBJECT
  184.  
  185. public:
  186.  
  187.     /**
  188.      *  Constructor.
  189.      *
  190.      *  @param parent Parent object of the part.
  191.      *  @param name   QT-internal name of the part.
  192.      */
  193.     Part( QObject *parent = 0, const char* name = 0 );
  194.  
  195.     /**
  196.      *  Destructor.
  197.      */
  198.     virtual ~Part();
  199.  
  200.     /**
  201.      * Embed this part into a host widget.
  202.      *
  203.      * You don't need to do this if you created the widget with the
  204.      * correct parent widget - this is just a QWidget::reparent().
  205.      * Note that the Part is still the holder
  206.      * of the QWidget, meaning that if you delete the Part,
  207.      * then the widget gets destroyed as well, and vice-versa.
  208.      * This method is not recommended since creating the widget with the correct
  209.      * parent is simpler anyway.
  210.      */
  211.     virtual void embed( QWidget * parentWidget );
  212.  
  213.     /**
  214.      * @return The widget defined by this part, set by setWidget().
  215.      */
  216.     virtual QWidget *widget();
  217.  
  218.     /**
  219.      * @internal
  220.      * Used by the part manager.
  221.      */
  222.     virtual void setManager( PartManager * manager );
  223.  
  224.     /**
  225.      * Returns the part manager handling this part, if any (0L otherwise).
  226.      */
  227.     PartManager * manager() const;
  228.  
  229.     /**
  230.      * Returns the part (this, or a child part) at the given global position.
  231.      * This is called by the part manager to ask whether a part should be activated
  232.      * when clicking somewhere. In most cases the default implementation is enough.
  233.      * Reimplement this if your part has child parts in some areas (like in khtml or koffice)
  234.      * @param widget the part widget being clicked - usually the same as widget(), except in koffice.
  235.      * @param globalPos the mouse coordinates in global coordinates
  236.      */
  237.     virtual Part *hitTest( QWidget *widget, const QPoint &globalPos );
  238.  
  239.     /**
  240.      *  @param selectable Indicates whether the part is selectable or not.
  241.      */
  242.     virtual void setSelectable( bool selectable );
  243.  
  244.     /**
  245.      *  Returns whether the part is selectable or not.
  246.      */
  247.     bool isSelectable() const;
  248.  
  249. signals:
  250.     /**
  251.      * Emitted by the part, to set the caption of the window(s)
  252.      * hosting this part
  253.      */
  254.     void setWindowCaption( const QString & caption );
  255.     /**
  256.      * Emited by the part, to set a text in the statusbar of the window(s)
  257.      * hosting this part
  258.      */
  259.     void setStatusBarText( const QString & text );
  260.  
  261. protected:
  262.  
  263.     /**
  264.      * Set the main widget.
  265.      *
  266.      * Call this in the Part-inherited class constructor.
  267.      */
  268.     virtual void setWidget( QWidget * widget );
  269.  
  270.     /**
  271.      * @internal
  272.      */
  273.     virtual void customEvent( QCustomEvent *event );
  274.  
  275.     /**
  276.      * Convenience method which is called when the Part received a PartActivateEvent .
  277.      * Reimplement this if you don't want to reimplement event and test for the event yourself
  278.      * or even install an event filter.
  279.      */
  280.     virtual void partActivateEvent( PartActivateEvent *event );
  281.  
  282.     /**
  283.      * Convenience method which is called when the Part received a
  284.      * PartSelectEvent .
  285.      * Reimplement this if you don't want to reimplement event and
  286.      * test for the event yourself or even install an event filter.
  287.      */
  288.     virtual void partSelectEvent( PartSelectEvent *event );
  289.  
  290.     /**
  291.      * Convenience method which is called when the Part received a
  292.      * GUIActivateEvent .
  293.      * Reimplement this if you don't want to reimplement event and
  294.      * test for the event yourself or even install an event filter.
  295.      */
  296.     virtual void guiActivateEvent( GUIActivateEvent *event );
  297.  
  298.     /**
  299.      * Convenience method for KXMLGUIFactory::container.
  300.      * @return a container widget owned by the Part's GUI.
  301.      */
  302.     QWidget *hostContainer( const QString &containerName );
  303.  
  304. private slots:
  305.     void slotWidgetDestroyed();
  306.  
  307. private:
  308.     QGuardedPtr<QWidget> m_widget;
  309.  
  310.     PartManager * m_manager;
  311.  
  312.     PartPrivate *d;
  313. };
  314.  
  315. class ReadWritePart;
  316. class ReadOnlyPartPrivate;
  317.  
  318. /**
  319.  * Base class for any "viewer" part.
  320.  *
  321.  * This class takes care of network transparency for you,
  322.  * in the simplest way (downloading to a temporary file, then letting the part
  323.  * load from the temporary file).
  324.  * To use the built-in network transparency, you only need to implement
  325.  * openFile(), not openURL().
  326.  *
  327.  * To implement network transparency differently (e.g. for progressive loading,
  328.  * like a web browser does for instance), or to prevent network transparency
  329.  * (but why would you do that?), you can override openURL().
  330.  *
  331.  * KParts Application can use the signals to show feedback while the URL is being loaded.
  332.  *
  333.  * ReadOnlyPart handles the window caption by setting it to the current URL
  334.  * (set in openURL(), and each time the part is activated).
  335.  * If you want another caption, set it in openFile() and
  336.  * (if the part might ever be used with a part manager) in guiActivateEvent()
  337.  */
  338. class KPARTS_EXPORT ReadOnlyPart : public Part
  339. {
  340.   Q_OBJECT
  341.   friend class ReadWritePart;
  342. public:
  343.   /**
  344.    * Constructor
  345.    * See also Part for the setXXX methods to call.
  346.    */
  347.   ReadOnlyPart( QObject *parent = 0, const char *name = 0 );
  348.  
  349.   /**
  350.    * Destructor
  351.    */
  352.   virtual ~ReadOnlyPart();
  353.  
  354.   /**
  355.    * Call this to turn off the progress info dialog used by
  356.    * the internal KIO job. Use this if you provide another way
  357.    * of displaying progress info (e.g. a statusbar), using the
  358.    * signals emitted by this class, and/or those emitted by
  359.    * the Job given by started.
  360.    */
  361.   void setProgressInfoEnabled( bool show );
  362.  
  363.   /**
  364.    * Returns whether the part shows the progress info dialog used by internal
  365.    * KIO job.
  366.    */
  367.   bool isProgressInfoEnabled() const;
  368.  
  369. #ifndef KDE_NO_COMPAT
  370.   void showProgressInfo( bool show );
  371. #endif
  372.  
  373. public slots:
  374.   /**
  375.    * Only reimplement openURL if you don't want the network transparency support
  376.    * to download from the url into a temporary file (when the url isn't local).
  377.    * Otherwise, reimplement openFile() only .
  378.    *
  379.    * If you reimplement it, don't forget to set the caption, usually with
  380.    * emit setWindowCaption( url.prettyURL() );
  381.    */
  382.   virtual bool openURL( const KURL &url );
  383.  
  384. public:
  385.   /**
  386.    *  Returns the currently in part used URL.
  387.    *
  388.    *  @return The current used URL.
  389.    */
  390.   KURL url() const { return m_url; }
  391.  
  392.   /**
  393.    * Called when closing the current url (e.g. document), for instance
  394.    * when switching to another url (note that openURL() calls it
  395.    * automatically in this case).
  396.    * If the current URL is not fully loaded yet, aborts loading.
  397.    * Deletes the temporary file used when the url is remote.
  398.    * @return always true, but the return value exists for reimplementations
  399.    */
  400.   virtual bool closeURL();
  401.  
  402. public:
  403.   /**
  404.    * Initiate sending data to this part.
  405.    * This is an alternative to openURL, which allows the user of the part
  406.    * to load the data itself, and send it progressively to the part.
  407.    *
  408.    * @param mimeType the type of data that is going to be sent to this part.
  409.    * @param url the URL representing this data. Although not directly used,
  410.    * every ReadOnlyPart has a URL (see url()), so this simply sets it.
  411.    * @return true if the part supports progressive loading and accepts data, false otherwise.
  412.    */
  413.   bool openStream( const QString& mimeType, const KURL& url );
  414.  
  415.   /**
  416.    * Send some data to the part. openStream must have been called previously,
  417.    * and must have returned true.
  418.    * @return true if the data was accepted by the part. If false is returned,
  419.    * the application should stop sending data, and doesn't have to call closeStream.
  420.    */
  421.   bool writeStream( const QByteArray& data );
  422.  
  423.   /**
  424.    * Terminate the sending of data to the part.
  425.    * With some data types (text, html...) closeStream might never actually be called,
  426.    * in the case of continuous streams, for instance plain text or HTML data.
  427.    */
  428.   bool closeStream();
  429.  
  430. private: // Makes no sense for inherited classes to call those. But make it protected there.
  431.  
  432.   /**
  433.    * Called by openStream to initiate sending of data.
  434.    * Parts which implement progress loading should check the @p mimeType
  435.    * parameter, and return true if they can accept a data stream of that type.
  436.    */
  437.   virtual bool doOpenStream( const QString& /*mimeType*/ ) { return false; }
  438.   /**
  439.    * Receive some data from the hosting application.
  440.    * In this method the part should attempt to display the data progressively.
  441.    * With some data types (text, html...) closeStream might never actually be called,
  442.    * in the case of continuous streams. This can't happen with e.g. images.
  443.    */
  444.   virtual bool doWriteStream( const QByteArray& /*data*/ ) { return false; }
  445.   /**
  446.    * This is called by closeStream(), to indicate that all the data has been sent.
  447.    * Parts should ensure that all of the data is displayed at this point.
  448.    * @return whether the data could be displayed correctly.
  449.    */
  450.   virtual bool doCloseStream() { return false; }
  451.  
  452. signals:
  453.   /**
  454.    * The part emits this when starting data.
  455.    * If using a KIO::Job, it sets the job in the signal, so that
  456.    * progress information can be shown. Otherwise, job is 0.
  457.    **/
  458.   void started( KIO::Job * );
  459.  
  460.   /**
  461.    * Emit this when you have completed loading data.
  462.    * Hosting apps will want to know when the process of loading the data
  463.    * is finished, so that they can access the data when everything is loaded.
  464.    **/
  465.   void completed();
  466.  
  467.   /**
  468.    * Same as the above signal except it indicates whether there is
  469.    * a pending action to be executed on a delay timer. An example of
  470.    * this is the meta-refresh tags on web pages used to reload/redirect
  471.    * after a certain period of time. This signal is useful if you want
  472.    * to give the user the ability to cancel such pending actions.
  473.    *
  474.    * @param pendingAction true if a pending action exists, false otherwise.
  475.    */
  476.   void completed( bool pendingAction );
  477.  
  478.   /**
  479.    * Emit this if loading is canceled by the user or by an error.
  480.    * @param errMsg the error message, empty if the user canceled the loading voluntarily.
  481.    */
  482.   void canceled( const QString &errMsg );
  483.  
  484. protected slots:
  485.   void slotJobFinished( KIO::Job * job );
  486.  
  487. protected:
  488.   /**
  489.    * If the part uses the standard implementation of openURL(),
  490.    * it must reimplement this, to open @p m_file.
  491.    * Otherwise simply define it to { return false; }
  492.    */
  493.   virtual bool openFile() = 0;
  494.  
  495.   /**
  496.    * @internal
  497.    */
  498.   void abortLoad();
  499.  
  500.   /**
  501.    * Reimplemented from Part, so that the window caption is set to
  502.    * the current url (decoded) when the part is activated.
  503.    * This is the usual behavior in 99% of the apps.
  504.    * Reimplement if you don't like it - test for event->activated() !
  505.    *
  506.    * Technical note : this is done with GUIActivateEvent and not with
  507.    * PartActivateEvent because it's handled by the mainwindow
  508.    * (which gets the even after the PartActivateEvent events have been sent)
  509.    */
  510.   virtual void guiActivateEvent( GUIActivateEvent *event );
  511.  
  512.   /**
  513.    * Remote (or local) url - the one displayed to the user.
  514.    */
  515.   KURL m_url;
  516.   /**
  517.    * Local file - the only one the part implementation should deal with.
  518.    */
  519.   QString m_file;
  520.   /**
  521.    * If @p true, @p m_file is a temporary file that needs to be deleted later.
  522.    */
  523.   bool m_bTemp;
  524.  
  525. private:
  526.   ReadOnlyPartPrivate *d;
  527. };
  528.  
  529. /**
  530.  * Base class for an "editor" part.
  531.  *
  532.  * This class handles network transparency for you.
  533.  * Anything that can open a URL, allow modifications, and save
  534.  * (to the same URL or a different one).
  535.  *
  536.  * A read-write part can be set to read-only mode, using setReadWrite().
  537.  *
  538.  * Part writers :
  539.  * Any part inheriting ReadWritePart should check isReadWrite()
  540.  * before allowing any action that modifies the part.
  541.  * The part probably wants to reimplement setReadWrite, disable those
  542.  * actions. Don't forget to call the parent setReadWrite().
  543.  */
  544. class KPARTS_EXPORT ReadWritePart : public ReadOnlyPart
  545. {
  546.   Q_OBJECT
  547. public:
  548.   /**
  549.    * Constructor.
  550.    * See parent constructor for instructions.
  551.    */
  552.   ReadWritePart( QObject *parent = 0, const char *name = 0 );
  553.   /**
  554.    * Destructor.
  555.    * Applications using a ReadWritePart should make sure, before
  556.    * destroying it, to call closeURL().
  557.    * In KMainWindow::queryClose(), for instance, they should allow
  558.    * closing only if the return value of closeURL() was true.
  559.    * This allows to cancel.
  560.    */
  561.   virtual ~ReadWritePart();
  562.  
  563.   /**
  564.    * @return true if the part is in read-write mode
  565.    */
  566.   bool isReadWrite() const { return m_bReadWrite; }
  567.  
  568.   /**
  569.    * Changes the behavior of this part to readonly or readwrite.
  570.    * @param readwrite set to true to enable readwrite mode
  571.    */
  572.   virtual void setReadWrite ( bool readwrite = true );
  573.  
  574.   /**
  575.    * @return true if the document has been modified.
  576.    */
  577.   bool isModified() const { return m_bModified; }
  578.  
  579.   /**
  580.    * If the document has been modified, ask the user to save changes.
  581.    * This method is meant to be called from KMainWindow::queryClose().
  582.    * It will also be called from closeURL().
  583.    *
  584.    * @return true if closeURL() can be called without the user losing
  585.    * important data, false if the user chooses to cancel.
  586.    *
  587.    * @since 3.2
  588.    */
  589.   // TODO: Make virtual for KDE 4
  590.   bool queryClose();
  591.  
  592.   /**
  593.    * Called when closing the current url (e.g. document), for instance
  594.    * when switching to another url (note that openURL() calls it
  595.    * automatically in this case).
  596.    *
  597.    * If the current URL is not fully loaded yet, aborts loading.
  598.    *
  599.    * If isModified(), queryClose() will be called.
  600.    *
  601.    * @return false on cancel
  602.    */
  603.   virtual bool closeURL();
  604.  
  605.   /**
  606.    * Call this method instead of the above if you need control if
  607.    * the save prompt is shown. For example, if you call queryClose()
  608.    * from KMainWindow::queryClose(), you would not want to prompt
  609.    * again when closing the url.
  610.    *
  611.    * Equivalent to promptToSave ? closeURL() : ReadOnlyPart::closeURL()
  612.    *
  613.    * @since 3.2
  614.    */
  615.   // TODO: Make virtual for KDE 4
  616.   bool closeURL( bool promptToSave );
  617.  
  618.   /**
  619.    * Save the file to a new location.
  620.    *
  621.    * Calls save(), no need to reimplement
  622.    */
  623.   virtual bool saveAs( const KURL &url );
  624.  
  625.   /**
  626.    *  Sets the modified flag of the part.
  627.    */
  628.   virtual void setModified( bool modified );
  629.  
  630. signals:
  631.    /**
  632.     * @since 3.2, remove in KDE 4, when queryClose is made virtual
  633.     *
  634.     * set handled to true, if you don't want the default handling
  635.     * set abortClosing to true, if you handled the request,
  636.     * but for any reason don't  want to allow closing the document
  637.     */
  638.    void sigQueryClose(bool *handled, bool* abortClosing);
  639.  
  640. public slots:
  641.   /**
  642.    * Call setModified() whenever the contents get modified.
  643.    * This is a slot for convenience, so that you can connect it
  644.    * to a signal, like textChanged().
  645.    */
  646.   virtual void setModified();
  647.  
  648.   /**
  649.    * Save the file in the location from which it was opened.
  650.    * You can connect this to the "save" action.
  651.    * Calls saveFile() and saveToURL(), no need to reimplement.
  652.    */
  653.   virtual bool save();
  654.  
  655.   /**
  656.    * Waits for any pending upload job to finish and returns whether the
  657.    * last save() action was successful.
  658.    */
  659.   bool waitSaveComplete();
  660.  
  661. protected:
  662.   /**
  663.    * Save to a local file.
  664.    * You need to implement it, to save to @p m_file.
  665.    * The framework takes care of re-uploading afterwards.
  666.    *
  667.    * @return true on success, false on failure.
  668.    * On failure the function should inform the user about the
  669.    * problem with an appropriate message box. Standard error
  670.    * messages can be constructed using KIO::buildErrorString()
  671.    * in combination with the error codes defined in kio/global.h
  672.    */
  673.   virtual bool saveFile() = 0;
  674.  
  675.   /**
  676.    * Save the file.
  677.    *
  678.    * Uploads the file, if @p m_url is remote.
  679.    * This will emit started(), and either completed() or canceled(),
  680.    * in case you want to provide feedback.
  681.    * @return true on success, false on failure.
  682.    */
  683.   virtual bool saveToURL();
  684.  
  685. protected slots:
  686.   /**
  687.    * @internal
  688.    */
  689.   void slotUploadFinished( KIO::Job * job );
  690.  
  691. private:
  692.   void prepareSaving();
  693.  
  694. private:
  695.   bool m_bModified;
  696.   bool m_bReadWrite;
  697.   bool m_bClosing;
  698. };
  699.  
  700. } // namespace
  701.  
  702. #endif
  703.